package com.frogs.ucenter.v1.service.impl;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.frogs.framework.util.PageList;
import com.frogs.framework.util.StringUtil;
import com.frogs.system.util.OrderStatusEnum;
import com.frogs.system.web.api.request.Request;
import com.frogs.system.web.api.response.Response;
import com.frogs.system.web.exception.ServiceOperationException;
import com.frogs.ucenter.component.RequestApiHelper;
import com.frogs.ucenter.dao.UserIntegralBalanceDao;
import com.frogs.ucenter.dao.UserRechargeBalanceDao;
import com.frogs.ucenter.dao.UserRechargeConsumeBackDao;
import com.frogs.ucenter.dao.UserRechargeConsumeRecordDao;
import com.frogs.ucenter.dao.UserRechargeRecordDao;
import com.frogs.ucenter.dao.UserRechargeStrategyDao;
import com.frogs.ucenter.entity.UserIntegralBalance;
import com.frogs.ucenter.entity.UserRechargeBalance;
import com.frogs.ucenter.entity.UserRechargeConsumeBack;
import com.frogs.ucenter.entity.UserRechargeRecord;
import com.frogs.ucenter.util.Constants;
import com.frogs.ucenter.util.SignVerifyUtil;
import com.frogs.ucenter.v1.request.RechargeBalanceRequest;
import com.frogs.ucenter.v1.request.RechargeListByDateRequest;
import com.frogs.ucenter.v1.request.RechargeStrategyRequest;
import com.frogs.ucenter.v1.request.UserRechargeAddRequest;
import com.frogs.ucenter.v1.request.UserRechargeConsumeBackRequest;
import com.frogs.ucenter.v1.request.UserRechargeListRequest;
import com.frogs.ucenter.v1.request.UserRechargePayCallbackRequest;
import com.frogs.ucenter.v1.request.UserRechargeRecordInfoRequest;
import com.frogs.ucenter.v1.request.UserRechargeUpdateRequest;
import com.frogs.ucenter.v1.response.AddResponse;
import com.frogs.ucenter.v1.response.DefaultResponse;
import com.frogs.ucenter.v1.response.PageListResponse;
import com.frogs.ucenter.v1.response.ShowResponse;
import com.frogs.ucenter.v1.response.UpdateResponse;
import com.frogs.ucenter.v1.service.UserRechargeRecordService;
import com.frogs.ucenter.v1.util.ApiConstants;

@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class) 
@Service(ApiConstants.VERSION+"userRechargeRecordService")
public class UserRechargeRecordServiceImpl extends UserRechargeStrategyBaseServiceImpl implements UserRechargeRecordService {
	
	private static final Logger log = LoggerFactory.getLogger(UserRechargeRecordServiceImpl.class);
	
	@Resource
	private UserRechargeRecordDao userRechargeRecordDao;
	@Resource
	private UserRechargeConsumeRecordDao userRechargeConsumeRecordDao;
	@Resource
	private UserRechargeConsumeBackDao userRechargeConsumeBackDao;
	@Resource
	private UserIntegralBalanceDao userIntegralBalanceDao;
	@Resource
	private UserRechargeBalanceDao userRechargeBalanceDao;
	@Resource
	private UserRechargeStrategyDao userRechargeStrategyDao;
	
	@Resource(name="requestApiHelper")
	private RequestApiHelper apiHelper;
	
	/**
	 * 创建充值记录
	 */
	@Override
	public Response addUserRechargeRecord(Request request) throws Exception {
		AddResponse<UserRechargeRecord> response = new AddResponse<UserRechargeRecord>();
		try {
			UserRechargeAddRequest userRechargeAddRequest = (UserRechargeAddRequest) request;
			log.info("func[addUserRechargeRecord] userRechargeAddRequest[" + userRechargeAddRequest.toString() + "] des[add recharge params]");
			UserRechargeRecord userRechargeRecord = new UserRechargeRecord();
			String rechargeCard = userRechargeAddRequest.getRechargeCard();
			String rechargeFrom = userRechargeAddRequest.getRechargeFrom();
			BigDecimal rechargeMoney = userRechargeAddRequest.getRechargeMoney();
			Integer userId = userRechargeAddRequest.getUserId();
			String orderId = "";
			Integer status = OrderStatusEnum.ORDER_STATUS_NOPAY.getId();
			userRechargeRecord = insertUserRechargeRecord(userId, rechargeMoney, 
					rechargeCard, rechargeFrom, orderId, status);
			response.setInfo(userRechargeRecord);
		} catch (Exception e) {
			log.error("func[{}] request[{}] exception[{}] desc[fail]",
					new Object[] { this.getClass().getName() +"."+Thread.currentThread().getStackTrace()[1].getMethodName(),
						request,Arrays.deepToString(e.getStackTrace()) });
			throw new ServiceOperationException("请求处理失败：" + e.getMessage());
		}
		return response;
	}
	
	private UserRechargeRecord insertUserRechargeRecord(Integer userId, BigDecimal rechargeMoney, 
			String rechargeCard, String rechargeFrom, String orderId, Integer status) {
		UserRechargeRecord userRechargeRecord = new UserRechargeRecord();
		userRechargeRecord.setRechargeCard(rechargeCard);
		userRechargeRecord.setRechargeFrom(rechargeFrom);
		userRechargeRecord.setRechargeMoney(rechargeMoney);
		userRechargeRecord.setUserId(userId);
		userRechargeRecord.setStatus(status);
		userRechargeRecordDao.insert(userRechargeRecord);
		return userRechargeRecord;
	}
	
	/**
	 * 更新充值记录
	 */
	@Override
	public Response update(Request request) throws Exception {
		UpdateResponse<UserRechargeRecord> response = new UpdateResponse<UserRechargeRecord>();
		try {
			UserRechargeUpdateRequest userRechargeUpdateRequest = (UserRechargeUpdateRequest) request;
			log.info("func[update] userRechargeUpdateRequest[" + userRechargeUpdateRequest.toString() + "] des[update recharge params]");
			UserRechargeRecord userRechargeRecord = userRechargeRecordDao.selectById(userRechargeUpdateRequest.getRecordId());
			if (userRechargeRecord == null) {
				throw new ServiceOperationException("该记录不存在");
			}
			userRechargeRecord = update(userRechargeUpdateRequest, userRechargeRecord);
			response.setInfo(userRechargeRecord);
		} catch (Exception e) {
			log.error("func[{}] request[{}] exception[{}] desc[fail]",
					new Object[] { this.getClass().getName() +"."+Thread.currentThread().getStackTrace()[1].getMethodName(),
						request,Arrays.deepToString(e.getStackTrace()) });
			throw new ServiceOperationException("请求处理失败：" + e.getMessage());
		}
		return response;
	}
	
	private UserRechargeRecord update(UserRechargeUpdateRequest userRechargeUpdateRequest, UserRechargeRecord userRechargeRecord) {
		userRechargeRecord.setRechargeCard(userRechargeUpdateRequest.getRechargeCard());
		userRechargeRecord.setRechargeFrom(userRechargeUpdateRequest.getRechargeFrom());
		userRechargeRecord.setRechargeMoney(userRechargeUpdateRequest.getRechargeMoney());
		userRechargeRecord.setStatus(OrderStatusEnum.ORDER_STATUS_NOPAY.getId());
		userRechargeRecordDao.update(userRechargeRecord);
		return userRechargeRecord;
	}
	
	/**
	 * 获取充值记录列表
	 */
	@Override
	public Response getUserRechargeRecordList(Request request) throws Exception {
		PageListResponse<Map<String, Object>> response = new PageListResponse<Map<String, Object>>();
		try {
			UserRechargeListRequest userRechargeListRequest = (UserRechargeListRequest) request;
			Integer userId = userRechargeListRequest.getUserId();
			Integer pageNo = userRechargeListRequest.getPageNo();
			Integer pageSize = userRechargeListRequest.getPageSize();
			Map<String, Object> params = new HashMap<String, Object>();
			int[] inStatusList = {OrderStatusEnum.ORDER_STATUS_YES.getId(),OrderStatusEnum.ORDER_STATUS_REFUND.getId()};
			params.put("eqUserId", userId);
			params.put("inStatusList", inStatusList);
			params.put("orderByClause", "recharge_time desc");
			PageList<Map<String, Object>> list = userRechargeRecordDao.selectAllByMap(params, pageNo, pageSize);
			response.setList(list);
			response.setPageTurn(list.getPageTurn());
		} catch (Exception e) {
			log.error("func[{}] request[{}] exception[{}] desc[fail]",
					new Object[] { this.getClass().getName() +"."+Thread.currentThread().getStackTrace()[1].getMethodName(),
						request,Arrays.deepToString(e.getStackTrace()) });
			throw new ServiceOperationException("请求处理失败：" + e.getMessage());
		}
		return response;
	}
	
	/**
	 * 获取充值记录信息
	 */
	@Override
	public Response getUserRechargeRecordInfo(Request request) throws Exception {
		ShowResponse<UserRechargeRecord> response = new ShowResponse<UserRechargeRecord>();
		try {
			UserRechargeRecordInfoRequest recordInfoRequest = (UserRechargeRecordInfoRequest) request;
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("eqUserId", recordInfoRequest.getUserId());
			params.put("eqId", recordInfoRequest.getRecordId());
			PageList<UserRechargeRecord> list = userRechargeRecordDao.selectByMap(params, false);
			if (list != null && list.size() > 0) {
				UserRechargeRecord userRechargeRecord = list.get(0);
				response.setInfo(userRechargeRecord);
			} else {
				throw new ServiceOperationException("该充值记录不存在");
			}
		} catch (Exception e) {
			log.error("func[{}] request[{}] exception[{}] desc[fail]",
					new Object[] { this.getClass().getName() +"."+Thread.currentThread().getStackTrace()[1].getMethodName(),
						request,Arrays.deepToString(e.getStackTrace()) });
			throw new ServiceOperationException("请求处理失败：" + e.getMessage());
		}
		return response;
	}

	/**
	 * 支付中心回调
	 */
	@Override
	public Response payCallback(Request request) throws Exception {
		DefaultResponse response = new DefaultResponse();
		try {
			UserRechargePayCallbackRequest payCallbackRequest = (UserRechargePayCallbackRequest) request;
			log.info("func[payCallback] payCallbackRequest[" + payCallbackRequest + "] desc[payCallback start]");
			if (!verifySign(payCallbackRequest)) {
				throw new ServiceOperationException("签名错误");
			}
			String rechargeId = payCallbackRequest.getOrderSn();
			if (StringUtil.isEmpty(rechargeId)) {
				throw new ServiceOperationException("充值Id为空");
			}
			UserRechargeRecord userRechargeRecord = userRechargeRecordDao.selectById(Integer.valueOf(rechargeId));
			if (userRechargeRecord == null) {
				throw new ServiceOperationException("该订单不存在");
			}
			if (userRechargeRecord.getStatus() == OrderStatusEnum.ORDER_STATUS_YES.getId()) {
				log.info("func[payCallback] status["+ OrderStatusEnum.ORDER_STATUS_YES.getId() +"] desc[this order is paied]");
				return response;
			}
			if (userRechargeRecord.getRechargeMoney().compareTo((BigDecimal)payCallbackRequest.getAmount()) != 0) {
				log.info("func[payCallback] rechargeMoney[" + userRechargeRecord.getRechargeMoney() + "] amout[" + payCallbackRequest.getAmount() + "] desc[amount is error]");
				throw new ServiceOperationException("价格有误");
			}
			Boolean flag = updateUserRechargeRecord(payCallbackRequest, userRechargeRecord);
			if (flag) {
				// 充值成功
				// 获取赠送金额
				BigDecimal money = this.giveMoney(payCallbackRequest.getAmount(), Integer.valueOf(rechargeId));
				log.info("func[payCallback] money[" + money + "] desc[giveMoney back]");
				this.rechargeBalance(payCallbackRequest.getAmount().add(money), userRechargeRecord.getUserId());
				BigDecimal integral = this.giveIntegral(payCallbackRequest.getAmount(), Integer.valueOf(rechargeId), userRechargeRecord.getUserId());
				log.info("func[payCallback] integral[" + integral + "] desc[giveIntegral back]");
				this.addIntegralBalance(integral.intValue(), userRechargeRecord.getUserId());
			}
			// 策略
		} catch (Exception e) {
			log.error("func[{}] request[{}] exception[{}] desc[fail]",
					new Object[] { this.getClass().getName() +"."+Thread.currentThread().getStackTrace()[1].getMethodName(),
						request,Arrays.deepToString(e.getStackTrace()) });
			throw new ServiceOperationException("请求处理失败：" + e.getMessage());
		}
		return response;
	}
	
	/**
	 * 更新积分
	 * 
	 * @param integral
	 * @param userId
	 */
	private void addIntegralBalance(Integer integral, Integer userId) {
		UserIntegralBalance userIntegralBalance = userIntegralBalanceDao.selectById(userId);
		if (null != userIntegralBalance) {
			Integer balance = userIntegralBalance.getIntegralUsable();
			Integer integralUsed = userIntegralBalance.getIntegralUsed();
			userIntegralBalance.setIntegralUsable(balance + integral);
			userIntegralBalance.setIntegralUsed(integralUsed - integral);
			userIntegralBalance.setUpdateTime(new Date());
			userIntegralBalanceDao.update(userIntegralBalance);
		} else {
			userIntegralBalance = new UserIntegralBalance();
			userIntegralBalance.setId(userId);
			userIntegralBalance.setIntegralUsable(integral);
			userIntegralBalance.setUpdateTime(new Date());
			userIntegralBalanceDao.insert(userIntegralBalance);
		}
	}
	
	/**
	 * 更新充值记录
	 * 
	 * @param payCallbackRequest
	 */
	private Boolean updateUserRechargeRecord(UserRechargePayCallbackRequest payCallbackRequest, UserRechargeRecord userRechargeRecord) {
		userRechargeRecord.setOrderId(payCallbackRequest.getSerialNo());
		if ("success".equals(payCallbackRequest.getStatus())) {
			userRechargeRecord.setStatus(OrderStatusEnum.ORDER_STATUS_YES.getId());
			userRechargeRecordDao.update(userRechargeRecord);
			log.info("func[updateUserRechargeRecord] desc[userRecharge success]");
			return true;
		} else {
			userRechargeRecord.setStatus(OrderStatusEnum.ORDER_STATUS_FAIL.getId());
			userRechargeRecordDao.update(userRechargeRecord);
			return false;
		}
		
	}
	
	/**
	 * 验证签名
	 * 
	 * @param payCallbackRequest
	 * @return
	 */
	private Boolean verifySign(UserRechargePayCallbackRequest payCallbackRequest) {
		if (StringUtil.isEmpty(payCallbackRequest.getSign())) {
			log.info("func[verifySign] desc[sign is null]");
			return false;
		}
		Map<String, String> params = new HashMap<String, String>();
		params.put("amount", payCallbackRequest.getAmount().toString());
		params.put("channelKey", payCallbackRequest.getChannelKey());
		params.put("orderDesc", payCallbackRequest.getOrderDesc());
		params.put("orderSn", payCallbackRequest.getOrderSn());
		params.put("orderSource", payCallbackRequest.getOrderSource());
		params.put("productName", payCallbackRequest.getProductName());
		params.put("serialNo", payCallbackRequest.getSerialNo());
		params.put("status", payCallbackRequest.getStatus());
		params.put("sign", payCallbackRequest.getSign());
		if (!SignVerifyUtil.verifySign(params, Constants.PAY_SIGN_KEY)) {
			log.info("func[verifySign] desc[sign is error]");
			return false;
		}
		return true;
	}

	@Override
	public Response backConsume(Request request) throws Exception {
		DefaultResponse response = new DefaultResponse();
		try {
			response.setCode(0);
			UserRechargeConsumeBackRequest backRequest = (UserRechargeConsumeBackRequest) request;
			//商城订单号
			String orderSn = backRequest.getOrderId();
			Integer userId = backRequest.getUserId();
			String rechargeCard = "";
			String rechargeFrom = "客户退款";
			BigDecimal rechargeMoney = backRequest.getConsumeMoney();
			String orderId = "";
			Integer state = OrderStatusEnum.ORDER_STATUS_REFUND.getId();
			//退款map
			Map<String ,Object> backMap = new HashMap<String ,Object>();
			backMap.put("eqOrderId", orderSn);
			//消费map
			Map<String ,Object> consumeMap = new HashMap<String ,Object>();
			consumeMap.put("eqOrderId", orderSn);
			consumeMap.put("eqUserId", userId);
			consumeMap.put("eqConsumeMoney", rechargeMoney);
			
			//判断商城的订单状态是否正常
			JSONObject json = apiHelper.getOrderStatus(orderSn);
			int status = json.getJSONObject("response").getJSONObject("orderInfo").getIntValue("status");
			if(OrderStatusEnum.ORDER_STATUS_REFUND.getId() == status){//判断订单的状态是否符合退款,如果符合,则进行后续退款操作
				//判断是否已经退过款,退过款则不能在进行退款
				int count = userRechargeConsumeBackDao.selectCountByMap(backMap);
				if(count<1){
					//判断是否存在此订单，订单金额是否正确,正确才允许退款
					count = userRechargeConsumeRecordDao.selectCountByMap(consumeMap);
					if(count>=1){
						//存在消费记录，则进行充值添加
						insertUserRechargeRecord(userId, rechargeMoney, rechargeCard, rechargeFrom, orderId, state);
						//同时修改余额表
						rechargeBalance(rechargeMoney, userId);
						//在退款记录表添加退款记录
						UserRechargeConsumeBack userRechargeConsumeBack = new UserRechargeConsumeBack(); 
						userRechargeConsumeBack.setOrderId(orderSn);
						userRechargeConsumeBackDao.insert(userRechargeConsumeBack);
						response.setCode(1);
					}
				}
			} else {
				response.setTip("订单状态不对");
			}
		} catch (Exception e) {
			log.error("func[{}] request[{}] exception[{}] desc[fail]",
					new Object[] { this.getClass().getName() +"."+Thread.currentThread().getStackTrace()[1].getMethodName(),
						request,Arrays.deepToString(e.getStackTrace()) });
			throw new ServiceOperationException("请求处理失败：" + e.getMessage());
		}
		return response;
	}

	@Override
	public Response getUserRechargeRecordListByDate(Request request) throws Exception {
		PageListResponse<Map<String, Object>> response = new PageListResponse<Map<String, Object>>();
		try {
			RechargeListByDateRequest rechargeListByDateRequest = (RechargeListByDateRequest) request;
			Date startDate = rechargeListByDateRequest.getStartDate();
			Date endDate = rechargeListByDateRequest.getEndDate();
			Integer pageNo = rechargeListByDateRequest.getPageNo();
			Integer pageSize = rechargeListByDateRequest.getPageSize();
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("startDate", startDate);
			params.put("endDate", endDate);
			params.put("orderByClause", "a.recharge_time asc");
			PageList<Map<String, Object>> list = userRechargeRecordDao.selectListByDate(params, pageNo, pageSize);
			response.setList(list);
			response.setPageTurn(list.getPageTurn());
		} catch (Exception e) {
			log.error("func[{}] request[{}] exception[{}] desc[fail]",
					new Object[] { this.getClass().getName() +"."+Thread.currentThread().getStackTrace()[1].getMethodName(),
						request,Arrays.deepToString(e.getStackTrace()) });
			throw new ServiceOperationException("请求处理失败：" + e.getMessage());
		}
		return response;
	}

	@Override
	public Response getUserRechargeBalanceList(Request request) throws Exception {
		PageListResponse<UserRechargeBalance> response = new PageListResponse<UserRechargeBalance>();
		try {
			RechargeBalanceRequest rechargeBalanceRequest = (RechargeBalanceRequest) request;
			Integer pageNo = rechargeBalanceRequest.getPageNo();
			Integer pageSize = rechargeBalanceRequest.getPageSize();
			Map<String, Object> params = new HashMap<String, Object>();
			PageList<UserRechargeBalance> list = userRechargeBalanceDao.selectByMap(params, pageNo, pageSize);
			response.setList(list);
			response.setPageTurn(list.getPageTurn());
		} catch (Exception e) {
			log.error("func[{}] request[{}] exception[{}] desc[fail]",
					new Object[] { this.getClass().getName() +"."+Thread.currentThread().getStackTrace()[1].getMethodName(),
						request,Arrays.deepToString(e.getStackTrace()) });
			throw new ServiceOperationException("请求处理失败：" + e.getMessage());
		}
		return response;
	}

	@Override
	public Response getUserRechargeStrategyList(Request request) throws Exception {
		PageListResponse<Map<String, Object>> response = new PageListResponse<Map<String, Object>>();
		try {
			RechargeStrategyRequest rechargeStrategyRequest = (RechargeStrategyRequest) request;
			Integer pageNo = rechargeStrategyRequest.getPageNo();
			Integer pageSize = rechargeStrategyRequest.getPageSize();
			Integer applicablePlatformId = rechargeStrategyRequest.getApplicablePlatformId();
			String expandCode = rechargeStrategyRequest.getExpandCode();
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("expandCode", expandCode);
			params.put("applicablePlatformId", applicablePlatformId);
			PageList<Map<String, Object>> list = userRechargeStrategyDao.selectUserStrategyByMap(params, pageNo, pageSize);
			response.setList(list);
			response.setPageTurn(list.getPageTurn());
		} catch (Exception e) {
			log.error("func[{}] request[{}] exception[{}] desc[fail]",
					new Object[] { this.getClass().getName() +"."+Thread.currentThread().getStackTrace()[1].getMethodName(),
						request,Arrays.deepToString(e.getStackTrace()) });
			throw new ServiceOperationException("请求处理失败：" + e.getMessage());
		}
		return response;
	}
	
}